package com.ssb.service.pay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apache.api.vo.ResultEntity;
import com.apache.cache.util.Validator;
import com.apache.exception.BusinessException;
import com.apache.ius.common.CommonUtils;
import com.apache.ius.plugin.IusPluginUtil;
import com.apache.tools.ConfigUtil;
import com.apache.tools.DataMap;
import com.apache.tools.StrUtil;
import com.apache.uct.common.ToolsUtil;
import com.ssb.util.QrCodeUtil;
import com.ssb.util.sign.*;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.filechooser.FileSystemView;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 微信支付接口业务处理
 */

@Service
public class WxPayService {
    private Logger log = Logger.getLogger(getClass());
    //3des加密测试key
    String testKey = "e8RbahwfDDiUJ3xz5geZFdF1SVBPvbep";
    //3des加密测试iv
    String testIv = "qhkKtbW+KlY=";
    //测试签名私钥路径
    String priKeyFilePath ="";
    //测试验签公钥路径
    String pubKeyFilePath = "";
    /**
     * 调用微信支付接口
     * @param mchCreateIp APP和网页支付提交用户端ip
     * @param infoId 产品唯一Id
     * @param exchangeNo 支付流水号
     * @return
     */
    public Map<String,String>  wxPayGetCodeUrl(String mchCreateIp , String infoId ,String exchangeNo,String type){
        //设置日期输出的格式
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyyMMddHHmmss");
        BigDecimal totalMoney =new BigDecimal("0");
        //固定配置
        String enterprise_num = CommonUtils.getConfigVal("enterprise_num");//保融分配的代表某个企业的编号
        String mch_id = CommonUtils.getConfigVal("mch_id");//商户号
        String sign_api_key = CommonUtils.getConfigVal("sign_api_key");//签名秘钥
        String br_wx_pay_url = CommonUtils.getConfigVal("br_wx_pay_url");//请求url

        //1、准备openId,若之前准备的已存储，可忽略。下面代码和auth2.jsp内逻辑一样。
        Map<String,String> resultWebData =new HashMap<String,String>();//最终反馈前端页面的js接口所需参数
        String body = "";
        String callFlag = "01";
        String outTradeNo = String.valueOf(System.currentTimeMillis());
        String fGTradeNo = "";

        try {
            Map<String,Object> whereMap = new HashMap<>();
            whereMap.put("ssInsurOrder.w_infoId",infoId);
            whereMap.put("ssInsurPro.infoId","[ssInsurOrder.proId]");
            whereMap.put("result_column","ssInsurOrder.tradeNo,ssInsurOrder.premium,ssInsurOrder.fGTradeNo,ssInsurPro.riskCname");
            ResultEntity resultEntity = IusPluginUtil.getInstance().select("ssb","obj", "s_ssInsurOrder,s_ssInsurPro", whereMap);
            DataMap dataMap = (DataMap)resultEntity.getEntity();
            if(!Validator.isEmpty(dataMap)){
                HashMap<String,Object> ssInsurOrderMap = (HashMap<String,Object>)dataMap.get("ssInsurOrder");
                HashMap<String,Object> ssInsurProMap = (HashMap<String,Object>)dataMap.get("ssInsurPro");
                if(exchangeNo.equals(String.valueOf(ssInsurOrderMap.get("tradeNo")))){
                    BigDecimal hundred = new BigDecimal("100");
                    totalMoney = new BigDecimal(String.valueOf(ssInsurOrderMap.get("premium")));
                    totalMoney = totalMoney.multiply(hundred);
                    body = String.valueOf(ssInsurProMap.get("riskCname"));//订单内容body
                    fGTradeNo = String.valueOf(ssInsurOrderMap.get("fGTradeNo"));
                }else {
                    new BusinessException("该订单号与支付流水号不匹配，请联系客服核实。");
                }
            }else {
                new BusinessException("该订单号下不存在订单，请联系客服核实。");
            }
            //订单总而
            String total_fee=String.valueOf(totalMoney.intValue());//单位是分
            //随机字符串
            String nonce_str=generateNonceStr();
            //通知地址
            String notify_url= CommonUtils.getConfigVal("br_wx_notify_url");;
            //附加数据


            Map<String, String> orderMap = new HashMap<String, String>();
            orderMap.put("EnterpriseNum",enterprise_num);
            orderMap.put("MchId",mch_id);
            orderMap.put("OutTradeNo",outTradeNo);
            orderMap.put("Body",body);
            orderMap.put("TotalFee",total_fee);
            orderMap.put("MchCreateIp",mchCreateIp);
            orderMap.put("NotifyUrl",notify_url);
            orderMap.put("CallFlag",callFlag);
            orderMap.put("ExchangeNo",exchangeNo);
            orderMap.put("NonceStr",nonce_str);
            orderMap.put("Attach",infoId);
//            priKeyFilePath = URLDecoder.decode(Thread.currentThread().getContextClassLoader().getResource("SendPrivateKey.xml").getPath(), "UTF-8");
            //此为测试环境的私钥   生产环境要切换一下
            priKeyFilePath = URLDecoder.decode(ConfigUtil.getClassLoaderPath()+"sign/SendPrivateKey.xml", "UTF-8");
            log.info("priKeyFilePath---->>>>>"+priKeyFilePath);
            log.info("orderMap---->>>>>"+orderMap.toString());

            String toSignData = SignUtil.getWebapiToSignData(orderMap, sign_api_key);
            log.info("toSignData---->>>>>"+toSignData);
            RSAHelper rsaHelper = getRsaHelper(priKeyFilePath, true);
            String signData = SignUtil.sign(rsaHelper, toSignData);
            log.info("Signature---->>>>>"+signData);
            orderMap.put("Signature",signData);

            String json = JSON.toJSONString(orderMap);

            //是否做3des加密自己这里改
            boolean isNeed3Des = false;
            String postData = getDataContent(isNeed3Des, json);
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-Type","application/x-www-form-urlencoded");
            Map<String, String> params = new HashMap<>(2);
            params.put("EnterpriseNum",enterprise_num);
            params.put("Data", postData);


            log.info("调起微信二维码支付请求参数params----->>>>>>"+params.toString());
            String resp = HttpUtil.sendKeyValuePost(br_wx_pay_url, headers, params);
            //解码验签
            String sourceData = getSourceData(isNeed3Des, URLDecoder.decode(resp, "UTF-8"));
            JSONObject jsonObj = JSON.parseObject(sourceData);
            log.info("返回参数===="+jsonObj);
            //{"Status":"0","EnterpriseNum":"AC110020","NonceStr":"1582873854189","ReturnMsg":"获取二维码成功","MchId":"0002900F1503037","FGTradeNo":"9163202002288014398685700096","Signature":"hRnQhbTR9aoSHb5sYZiuuJAp9pMBaewDzMgG82eDZSXjfGvbjH5zKoCKyCvDlYGpQ0+5CC+8HvXSMOwAEb+G6M0gSIgzoidnH+SO+RAQ4bMjvzB0xy4FVBEbg5MnRmK//Ibqe1c7EfWEeqCo7j5hl+EQnKHTNU1RRTmS5GhwIaw=","CodeImgUrl":"https://rhfwebapiuat.fingard.cn/codeImg/AC110020/202002/1582874040943.png","CodeUrl":"https://rhfwebapiuat.fingard.cn/webApi/CodeUrlMap/7fb6d76828c34c9e83b3c75998e7713b"}

            //非-1返回，需要验签
            if (jsonObj.containsKey("Status") && jsonObj.getIntValue("Status") == 0)
            {
                Map<String, Object> rmap = parseJSON2Map(sourceData);
                if (rmap.size() > 0 && rmap.containsKey("class"))
                {
                    rmap.remove("class");
                }
                String toSignData2 = SignUtil.getWebapiToSignDataFromMap(rmap, sign_api_key);
//                pubKeyFilePath = this.getClass().getClassLoader().getResource("RecPublicKey.xml").getPath());
                //RecPublicKeyUat为测试环境的密钥   生产环境要换回来
                pubKeyFilePath = URLDecoder.decode(ConfigUtil.getClassLoaderPath()+"sign/RecPublicKey.xml", "UTF-8");
                RSAHelper rsaHelper2 = getRsaHelper(pubKeyFilePath,false);
                if (!SignUtil.verifySign(rsaHelper2, toSignData2, Base64Helper.decode(jsonObj.get("Signature").toString())))
                {
                    resultWebData.put("msg","验签失败");
                    resultWebData.put("flag","F");

                }
                else {
                    //0--app支付直接返回 codeUrl;  1-- web端支付需要将url转换成二维码图片
                    switch (type){
                        case "0" :
                            log.info("APP支付请求参数URL===="+jsonObj.get("CodeUrl"));
                            resultWebData.put("msg",String.valueOf(jsonObj.get("ReturnMsg")));
                            resultWebData.put("flag","T");
                            resultWebData.put("codeUrl",String.valueOf(jsonObj.get("CodeUrl")));
                            if(!fGTradeNo.equals(String.valueOf(jsonObj.get("FGTradeNo")))){
                                Map<String,Object> saveMap = new HashMap<>();
                                saveMap.put("ssInsurOrder.w_infoId",infoId);
                                saveMap.put("ssInsurOrder.fGTradeNo",jsonObj.get("FGTradeNo"));
                                IusPluginUtil.getInstance().saveInvoke("ssb",  "u_ssInsurOrder", saveMap);
                            }
                            break;
                        case "1" :
                            //请求成功后将二维码上传服务器，返回下载链接
                            //上传
                            String fileUploadDirectory = ToolsUtil.getInstance().getLocalByKey("config.properties", "UPLOAD_DIRECTORY");//获取文件需要上传到的根目录
                            String uploadRoot = fileUploadDirectory + "/atta/"; //获取文件需要上传到的根目录
                            String sysEname = CommonUtils.getSysEname();
                            String uploadPath = uploadRoot + sysEname + "/";
                            String dirName = "wxpay";
                            uploadPath += dirName;// 上传目录
                            String filename = infoId+".png";
                            String payImgQrCode = QrCodeUtil.createQrCode(String.valueOf(jsonObj.get("CodeUrl")), uploadPath,filename);
                            log.info("payImgQrCode===="+payImgQrCode);
                            File filepath = new File(payImgQrCode);//创建新文件
                            if (!filepath.getParentFile().exists()) { // 判断路径是否存在，不存在则新创建一个
                                filepath.getParentFile().mkdirs();
                            }
                            if (!filepath.exists()){
                                filepath.createNewFile();
                            }

                            //下载
                            String fileDownloadUrl = ToolsUtil.getInstance().getLocalByKey("config.properties", "DOWNLOAD_URL");//获取文件需要下载的根目录地址
                            String downloadRoot = fileDownloadUrl + "/atta/";//获取文件需要下载的根目录
                            String downloadPath = downloadRoot + sysEname + File.separator;
                            downloadPath += dirName + File.separator + filename;
                            downloadPath = downloadPath.replaceAll("\\\\", "/");

                            resultWebData.put("msg",String.valueOf(jsonObj.get("ReturnMsg")));
                            resultWebData.put("flag","T");
                            resultWebData.put("wxPayImage", downloadPath);

                            log.info("二维码请求参数URL===="+jsonObj.get("CodeUrl"));
                            log.info("返回二维码下载路径===="+resultWebData.get("wxPayImage"));
                            if(!fGTradeNo.equals(String.valueOf(jsonObj.get("FGTradeNo")))){
                                Map<String,Object> saveMap = new HashMap<>();
                                saveMap.put("ssInsurOrder.w_infoId",infoId);
                                saveMap.put("ssInsurOrder.fGTradeNo",jsonObj.get("FGTradeNo"));
                                IusPluginUtil.getInstance().saveInvoke("ssb",  "u_ssInsurOrder", saveMap);
                            }
                            break;
                        default: break;
                    }
                }

            }else{
                resultWebData.put("msg",String.valueOf(jsonObj.get("ReturnMsg")));
                resultWebData.put("flag","F");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultWebData;

    }
    /**
     * 小程序调用微信支付接口
     * @param mchCreateIp APP和网页支付提交用户端ip
     * @param infoId 产品唯一Id
     * @param exchangeNo 支付流水号
     * @param openId 小程序用户的唯一标识
     * @return
     */
    public Map<String,String> wxPayMiniProgram(String mchCreateIp , String infoId ,String exchangeNo,String openId){
        //设置日期输出的格式
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyyMMddHHmmss");
        BigDecimal totalMoney =new BigDecimal("0");
        //固定配置
        String enterprise_num = CommonUtils.getConfigVal("enterprise_num");//保融分配的代表某个企业的编号
        String mch_id = CommonUtils.getConfigVal("mini_program_mch_id");//商户号
        String sign_api_key = CommonUtils.getConfigVal("sign_api_key");//签名秘钥
        String br_wx_pay_url = CommonUtils.getConfigVal("br_wx_pay_mini_program_url");//请求url

        //1、准备openId,若之前准备的已存储，可忽略。下面代码和auth2.jsp内逻辑一样。
        Map<String,String> resultWebData =new HashMap<String,String>();//最终反馈前端页面的js接口所需参数
        String body = "";

        String outTradeNo = String.valueOf(System.currentTimeMillis());
        String fGTradeNo = "";
        try {
            Map<String,Object> whereMap = new HashMap<>();
            whereMap.put("ssInsurOrder.w_infoId",infoId);
            whereMap.put("ssInsurPro.infoId","[ssInsurOrder.proId]");
            whereMap.put("result_column","ssInsurOrder.tradeNo,ssInsurOrder.premium,ssInsurOrder.fGTradeNo,ssInsurPro.riskCname");
            ResultEntity resultEntity = IusPluginUtil.getInstance().select("ssb","obj", "s_ssInsurOrder,s_ssInsurPro", whereMap);
            DataMap dataMap = (DataMap)resultEntity.getEntity();
            if(!Validator.isEmpty(dataMap)){
                HashMap<String,Object> ssInsurOrderMap = (HashMap<String,Object>)dataMap.get("ssInsurOrder");
                HashMap<String,Object> ssInsurProMap = (HashMap<String,Object>)dataMap.get("ssInsurPro");
                if(exchangeNo.equals(String.valueOf(ssInsurOrderMap.get("tradeNo")))){
                    BigDecimal hundred = new BigDecimal("100");
                    totalMoney = new BigDecimal(String.valueOf(ssInsurOrderMap.get("premium")));
                    totalMoney = totalMoney.multiply(hundred);
                    body = String.valueOf(ssInsurProMap.get("riskCname"));//订单内容body
                    fGTradeNo = String.valueOf(ssInsurOrderMap.get("fGTradeNo"));
                }else {
                    new BusinessException("该订单号与支付流水号不匹配，请联系客服核实。");
                }
            }else {
                new BusinessException("该订单号下不存在订单，请联系客服核实。");
            }
            //订单总而
            String total_fee=String.valueOf(totalMoney.intValue());//单位是分
            //随机字符串
            String nonce_str=generateNonceStr();
            //通知地址
            String notify_url= CommonUtils.getConfigVal("br_wx_notify_url");;
            //是否小程序支付，1：是，0：不是，默认0
            String isMiniPg = "1";
            //缴费成功后除了正常结果通知是否还需要调外部系统，00：不回调，01：调用见费，默认为00，只做正常结果通知
            String callFlag = "01";
            Map<String,Object> appConfig_xcx = (Map<String,Object>)CommonUtils.getCacheByAppConfig("wechat_xcx");
            Map<String,String> mapAppId = (Map<String,String>)appConfig_xcx.get("wechat_xcx_appId");
            String appId = String.valueOf(mapAppId.get("appValue"));

            Map<String, String> orderMap = new HashMap<String, String>();
            orderMap.put("EnterpriseNum",enterprise_num);
            orderMap.put("MchId",mch_id);
            orderMap.put("AppId",appId);
            orderMap.put("OutTradeNo",outTradeNo);
            orderMap.put("IsMiniPg",isMiniPg);
            orderMap.put("Body",body);
            orderMap.put("TotalFee",total_fee);
            orderMap.put("MchCreateIp",mchCreateIp);
            orderMap.put("NotifyUrl",notify_url);
            orderMap.put("CallFlag",callFlag);
            orderMap.put("ExchangeNo",exchangeNo);
            orderMap.put("OpenId",openId);
            orderMap.put("NonceStr",nonce_str);
            //附加信息，作为扩展，在回调通知中会原样返回
            orderMap.put("Attach",infoId);
//            priKeyFilePath = URLDecoder.decode(Thread.currentThread().getContextClassLoader().getResource("SendPrivateKey.xml").getPath(), "UTF-8");
            priKeyFilePath = URLDecoder.decode(ConfigUtil.getClassLoaderPath()+"sign/SendPrivateKey.xml", "UTF-8");
//            log.info("priKeyFilePath---->>>>>"+priKeyFilePath);
            log.info("orderMap---->>>>>"+orderMap.toString());

            String toSignData = SignUtil.getWebapiToSignData(orderMap, sign_api_key);
            RSAHelper rsaHelper = getRsaHelper(priKeyFilePath, true);
            String signData = SignUtil.sign(rsaHelper, toSignData);

            orderMap.put("Signature",signData);
            String json = JSON.toJSONString(orderMap);

            //是否做3des加密自己这里改
            boolean isNeed3Des = false;
            String postData = getDataContent(isNeed3Des, json);
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-Type","application/x-www-form-urlencoded");
            Map<String, String> params = new HashMap<>(2);
            params.put("EnterpriseNum",enterprise_num);
            params.put("Data", postData);


            log.info("调起微信支付请求参数params----->>>>>>"+params.toString());
            String resp = HttpUtil.sendKeyValuePost(br_wx_pay_url, headers, params);
            //解码验签
            String sourceData = getSourceData(isNeed3Des, URLDecoder.decode(resp, "UTF-8"));
            JSONObject jsonObj = JSON.parseObject(sourceData);
            log.info("返回参数===="+jsonObj);
            //{"Status":"0","EnterpriseNum":"AC110020","NonceStr":"1582873854189","ReturnMsg":"获取二维码成功","MchId":"0002900F1503037","FGTradeNo":"9163202002288014398685700096","Signature":"hRnQhbTR9aoSHb5sYZiuuJAp9pMBaewDzMgG82eDZSXjfGvbjH5zKoCKyCvDlYGpQ0+5CC+8HvXSMOwAEb+G6M0gSIgzoidnH+SO+RAQ4bMjvzB0xy4FVBEbg5MnRmK//Ibqe1c7EfWEeqCo7j5hl+EQnKHTNU1RRTmS5GhwIaw=","CodeImgUrl":"https://rhfwebapiuat.fingard.cn/codeImg/AC110020/202002/1582874040943.png","CodeUrl":"https://rhfwebapiuat.fingard.cn/webApi/CodeUrlMap/7fb6d76828c34c9e83b3c75998e7713b"}

            //非-1返回，需要验签
            if (jsonObj.containsKey("Status") && jsonObj.getIntValue("Status") == 0)
            {
                Map<String, Object> rmap = parseJSON2Map(sourceData);
                if (rmap.size() > 0 && rmap.containsKey("class"))
                {
                    rmap.remove("class");
                }
                String toSignData2 = SignUtil.getWebapiToSignDataFromMap(rmap, sign_api_key);
//                pubKeyFilePath = this.getClass().getClassLoader().getResource("RecPublicKey.xml").getPath());
                pubKeyFilePath = URLDecoder.decode(ConfigUtil.getClassLoaderPath()+"sign/RecPublicKey.xml", "UTF-8");
                RSAHelper rsaHelper2 = getRsaHelper(pubKeyFilePath,false);
                if (!SignUtil.verifySign(rsaHelper2, toSignData2, Base64Helper.decode(jsonObj.get("Signature").toString())))
                {
                    resultWebData.put("msg","验签失败");
                    resultWebData.put("flag","F");

                }else {
                    resultWebData.put("msg",String.valueOf(jsonObj.get("ReturnMsg")));
                    resultWebData.put("flag","T");
                    resultWebData.put("payInfo",String.valueOf(jsonObj.get("PayInfo")));
                    if(!fGTradeNo.equals(String.valueOf(jsonObj.get("FGTradeNo")))){
                        Map<String,Object> saveMap = new HashMap<>();
                        saveMap.put("ssInsurOrder.w_infoId",infoId);
                        saveMap.put("ssInsurOrder.fGTradeNo",jsonObj.get("FGTradeNo"));
                        IusPluginUtil.getInstance().saveInvoke("ssb",  "u_ssInsurOrder", saveMap);
                    }
                }


            }else{
                resultWebData.put("msg",String.valueOf(jsonObj.get("ReturnMsg")));
                resultWebData.put("flag","F");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultWebData;

    }

    /**
     * APP调用微信支付预下单接口
     * @param mchCreateIp APP和网页支付提交用户端ip
     * @param infoId 产品唯一Id
     * @param exchangeNo 支付流水号
     * @param appId 微信开放平台审核通过的移动应用AppID
     * @return
     */
    public Map<String, String> wxPayAppProgram(String mchCreateIp, String infoId, String exchangeNo, String appId) {

        BigDecimal totalMoney =new BigDecimal("0");
        //固定配置
        String enterprise_num = CommonUtils.getConfigVal("enterprise_num");//保融分配的代表某个企业的编号
        String mch_id = CommonUtils.getConfigVal("mini_program_mch_id");//商户号
        String sign_api_key = CommonUtils.getConfigVal("sign_api_key");//签名秘钥
        String br_wx_pay_url = CommonUtils.getConfigVal("br_wx_pay_app_progran_url");//请求url

        //1、准备openId,若之前准备的已存储，可忽略。下面代码和auth2.jsp内逻辑一样。
        Map<String,String> resultWebData =new HashMap<String,String>();//最终反馈前端页面的js接口所需参数
        String body = "";

        String outTradeNo = String.valueOf(System.currentTimeMillis());
        try {
            Map<String,Object> whereMap = new HashMap<>();
            whereMap.put("ssInsurOrder.w_infoId",infoId);
            whereMap.put("ssInsurPro.infoId","[ssInsurOrder.proId]");
            whereMap.put("result_column","ssInsurOrder.tradeNo,ssInsurOrder.premium,ssInsurOrder.fGTradeNo,ssInsurPro.riskCname");
            ResultEntity resultEntity = IusPluginUtil.getInstance().select("ssb","obj", "s_ssInsurOrder,s_ssInsurPro", whereMap);
            DataMap dataMap = (DataMap)resultEntity.getEntity();
            if(!Validator.isEmpty(dataMap)){
                HashMap<String,Object> ssInsurOrderMap = (HashMap<String,Object>)dataMap.get("ssInsurOrder");
                HashMap<String,Object> ssInsurProMap = (HashMap<String,Object>)dataMap.get("ssInsurPro");
                if(exchangeNo.equals(String.valueOf(ssInsurOrderMap.get("tradeNo")))){
                    BigDecimal hundred = new BigDecimal("100");
                    totalMoney = new BigDecimal(String.valueOf(ssInsurOrderMap.get("premium")));
                    totalMoney = totalMoney.multiply(hundred);
                    body = String.valueOf(ssInsurProMap.get("riskCname"));//订单内容body
                }else {
                    new BusinessException("该订单号与支付流水号不匹配，请联系客服核实。");
                }
            }else {
                new BusinessException("该订单号下不存在订单，请联系客服核实。");
            }
            //订单总而
            String total_fee=String.valueOf(totalMoney.intValue());//单位是分
            //随机字符串
            String nonce_str=generateNonceStr();
            //通知地址
            String notify_url= CommonUtils.getConfigVal("br_wx_notify_url");;

            Map<String, String> orderMap = new HashMap<String, String>();

            orderMap.put("EnterpriseNum",enterprise_num);
            orderMap.put("MchId",mch_id);
            orderMap.put("OutTradeNo",outTradeNo);
            orderMap.put("Body",body);
            orderMap.put("TotalFee",total_fee);
            orderMap.put("MchCreateIp",mchCreateIp);
            orderMap.put("NotifyUrl",notify_url);
            orderMap.put("NonceStr",nonce_str);
            orderMap.put("SubAppid",appId);
            //附加信息，作为扩展，在回调通知中会原样返回
            orderMap.put("Attach",infoId);
//            priKeyFilePath = URLDecoder.decode(Thread.currentThread().getContextClassLoader().getResource("SendPrivateKey.xml").getPath(), "UTF-8");
            priKeyFilePath = URLDecoder.decode(ConfigUtil.getClassLoaderPath()+"sign/SendPrivateKey.xml", "UTF-8");
//            log.info("priKeyFilePath---->>>>>"+priKeyFilePath);
            log.info("orderMap---->>>>>"+orderMap.toString());

            String toSignData = SignUtil.getWebapiToSignData(orderMap, sign_api_key);
            RSAHelper rsaHelper = getRsaHelper(priKeyFilePath, true);
            String signData = SignUtil.sign(rsaHelper, toSignData);

            orderMap.put("Signature",signData);
            String json = JSON.toJSONString(orderMap);

            //是否做3des加密自己这里改
            boolean isNeed3Des = false;
            String postData = getDataContent(isNeed3Des, json);
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-Type","application/x-www-form-urlencoded");
            Map<String, String> params = new HashMap<>(2);
            params.put("EnterpriseNum",enterprise_num);
            params.put("Data", postData);


            log.info("APP调起微信支付预下单请求参数params----->>>>>>"+params.toString());
            String resp = HttpUtil.sendKeyValuePost(br_wx_pay_url, headers, params);
            //解码验签
            String sourceData = getSourceData(isNeed3Des, URLDecoder.decode(resp, "UTF-8"));
            JSONObject jsonObj = JSON.parseObject(sourceData);
            log.info("返回参数===="+jsonObj);

            //非-1返回，需要验签
            if (jsonObj.containsKey("Status") && jsonObj.getIntValue("Status") == 0)
            {
                Map<String, Object> rmap = parseJSON2Map(sourceData);
                if (rmap.size() > 0 && rmap.containsKey("class"))
                {
                    rmap.remove("class");
                }
                String toSignData2 = SignUtil.getWebapiToSignDataFromMap(rmap, sign_api_key);
//                pubKeyFilePath = this.getClass().getClassLoader().getResource("RecPublicKey.xml").getPath());
                pubKeyFilePath = URLDecoder.decode(ConfigUtil.getClassLoaderPath()+"sign/RecPublicKey.xml", "UTF-8");
                RSAHelper rsaHelper2 = getRsaHelper(pubKeyFilePath,false);
                if (!SignUtil.verifySign(rsaHelper2, toSignData2, Base64Helper.decode(jsonObj.get("Signature").toString())))
                {
                    resultWebData.put("msg","验签失败");
                    resultWebData.put("flag","F");

                }else {
                    resultWebData.put("msg",String.valueOf(jsonObj.get("ReturnMsg")));
                    resultWebData.put("flag","T");
                    resultWebData.put("payInfo",String.valueOf(jsonObj.get("PayInfo")));
                }
            }else{
                resultWebData.put("msg",String.valueOf(jsonObj.get("ReturnMsg")));
                resultWebData.put("flag","F");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultWebData;
    }


    /**
     * 支付成功后回调方法
     * @param request
     * @param response
     */
    public void wxPayNotify(HttpServletRequest request, HttpServletResponse response){
        BufferedReader reader = null;
        PrintWriter out=null;

        try {
            String msg = request.getParameterNames().nextElement();
            //解码验签
            String sourceData = getSourceData(false, URLDecoder.decode(msg, "UTF-8"));
            log.info("sourceData--------->>>>>>>"+sourceData);
            /**
             * {
             *     "Status":"0",
             *     "CallResult":"3",
             *     "NonceStr":"1582882810873",
             *     "FeeType":"CNY",
             *     "ReturnMsg":"",
             *     "OutTradeNo":"1582882807040",
             *     "MchId":"0002900F1503037",
             *     "Attach":"pk218792553300885504",
             *     "FGTradeNo":"9163202002288014470498336768",
             *     "TimeEnd":"20200228174314",
             *     "OpenId":"oWikB07PhXLKfYtr-5aQJXiEXkdo",
             *     "EnterpriseNum":"AC110020",
             *     "TotalFee":"1",
             *     "IsSubscribe":"",
             *     "BankBillNo":"",
             *     "Signature":"MzxXgvA41M4zF1JvDlw5vJ0AMa1K59MVShaJ/TiVHaiDbh092ojLIxIKPbnEL4P5yXZygeAGmGYoJZj3AskT0gjnU0dR7GwcmiqFUSDUpqTqPuV51WjyFXVJC91yI1JdwnQyJ4xnE1WEfdBeSdX9XqUjsCpYZTJtfgyCbqy69sU=",
             *     "TradeState":"SUCCESS",
             *     "BankType":"",
             *     "Transaction_id":"020479145191"
             * }
             */
            if(StrUtil.isNotNull(sourceData)) {
                JSONObject json = JSON.parseObject(sourceData);
                Map<String,Object> whereMap = new HashMap<>();
                whereMap.put("ssInsurOrder.w_infoId",json.get("Attach"));
                ResultEntity objEntity = IusPluginUtil.getInstance().select("ssb", "obj", "s_ssInsurOrder", whereMap);
                DataMap dataMap = (DataMap)objEntity.getEntity();
                if(!Validator.isEmpty(dataMap)&&!"3".equals(dataMap.get("orderStatus"))&&!"4".equals(dataMap.get("orderStatus"))){
                    Map<String,Object> saveMap = new HashMap<>();
                    saveMap.put("ssInsurOrder.w_infoId",json.get("Attach"));
                    saveMap.put("ssInsurOrder.orderStatus","4");
                    IusPluginUtil.getInstance().saveInvoke("ssb",  "u_ssInsurOrder", saveMap);
                }
                if("SUCCESS".equals(json.get("TradeState"))){
                    //告诉微信服务器，我收到信息了，不要在调用回调action了
                    out = response.getWriter();
                    out.write("success");
                    out.flush();
                    log.info("\n----SUCCESS---！！");
                }
                log.info("\n----结束---！！");

            }
        } catch (Exception e) {

        }finally {
            if (out != null) {
                out.close();
            }
            if(reader !=null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final Random RANDOM = new SecureRandom();


    /**
     * 获取随机字符串 Nonce Str
     *
     * @return String 随机字符串
     */
    public static String generateNonceStr() {
        char[] nonceChars = new char[32];
        for (int index = 0; index < nonceChars.length; ++index) {
            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        }
        return new String(nonceChars);
    }
    /**
     * Discription 初始化RSA签名工具类
     * @author Don
     * @date 2018/9/6 17:45
     * @param
     * @return
     */
    private RSAHelper getRsaHelper(String prikeyFilePath, boolean isForSign) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException
    {
        RSAHelper rsaHelper = new RSAHelper();
        if (isForSign)
        {
            rsaHelper.setPrivateKeyByXml(prikeyFilePath);
        }
        else {
            rsaHelper.setPublicKeyByXml(prikeyFilePath);
        }
        return rsaHelper;
    }

    /**
     * Discription 获取Data请求内容
     * @author Don
     * @date 2018/9/6 18:36
     * @param
     * @return
     */
    private String getDataContent(boolean is3des, String sourceJson) throws Exception
    {
        String str = "";
        //3des加密
        if (is3des)
        {
            byte[] bytes = sourceJson.getBytes("GBK");
            TripleDESHelper tripleDESHelper = new TripleDESHelper();
            tripleDESHelper.initCBC(testKey, testIv);
            bytes = tripleDESHelper.encrypt(bytes);
            str = Base64.getEncoder().encodeToString(bytes);
        }
        else {
            byte[] bytes = sourceJson.getBytes("UTF-8");
            str = Base64Helper.encode(bytes);
            str = URLEncoder.encode(str, "UTF-8");
        }

        return str;
    }

    /**
     * Discription 获取原始数据
     * @author Don
     * @date 2018/9/6 9:43
     * @param
     * @return
     */
    private String getSourceData(boolean is3des, String encryptBase64Data) throws Exception
    {
        String sourceData = encryptBase64Data;
        if (is3des)
        {
            TripleDESHelper tripleDESHelper = new TripleDESHelper();
            tripleDESHelper.initCBC(testKey, testIv);
            sourceData = tripleDESHelper.decrypt(encryptBase64Data);
        }
        sourceData = new String(Base64Helper.decode(sourceData), "UTF-8");
        return sourceData;
    }

    /**
     * Discription json字符串转map
     * @author Don
     * @date 2018/9/7 11:47
     * @param
     * @return
     */
    public static Map<String, Object> parseJSON2Map(String jsonStr){
        Map<String, Object> map = new HashMap<String, Object>();
        JSONObject json = JSON.parseObject(jsonStr);
        for(Object k : json.keySet()){
            Object v = json.get(k);
            if(v instanceof JSONArray){
                List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
                JSONArray arr = (JSONArray) v;
                for (int i = 0; i < arr.size(); i++) {
                    list.add(parseJSON2Map(arr.getJSONObject(i).toString()));
                }
                map.put(k.toString(), list);
            } else {
                map.put(k.toString(), v);
            }
        }
        return map;
    }

}
